
let models = ['qwen-max', 'qwen-plus']
let chatHistory = []; // 存储完整的对话历史 {role, content}
const chatMessages = document.getElementById('chat-messages');
const messageInput = document.getElementById('message-input');
const sendButton = document.getElementById('send-button');

// ================== 新增 Wiki 转换函数 ==================

function wikiToHtml(text) {

    // 转换代码块
    let codes = []
    let quotes = []
    text = text.trim()
    text = text.replace(/``` *(\w+)? *\n([\s\S]*?)\n *```/g, (match, lang, code) => {
        let idx = codes.length;
        codes.push({
            "lang": lang || '',
            "code": code.trim().replace(/</g, '&lt;').replace(/>/g, '&gt;')
        })
        return `<coding>${idx}</coding>`
    });

    text = text.replace(/`([^`]*?)`/g, (match, quote) => {
        let idx = quotes.length;
        quotes.push(quote.trim().replace(/</g, '&lt;').replace(/>/g, '&gt;'))
        return `<quote>${idx}</quote>`
    });

    // 转换标题
    text = text.replace(/^===(.+?)===/gm, '<h3>$1</h3>');
    text = text.replace(/^==(.+?)==/gm, '<h4>$1</h4>');
    text = text.replace(/^=(.+?)=/gm, '<h5>$1</h5>');
    text = text.replace(/^##### +([\s\S]*?)$/gm, '<h7>$1</h7>');
    text = text.replace(/^#### +([\s\S]*?)$/gm, '<h6>$1</h6>');
    text = text.replace(/^### +([\s\S]*?)$/gm, '<h5>$1</h5>');
    text = text.replace(/^## +([\s\S]*?)$/gm, '<h4>$1</h4>');
    text = text.replace(/^# +([\s\S]*?)$/gm, '<h3>$1</h3>');
    // 分割线
    text = text.replace(/^-{3,} *$/gm, '<div class="divider"></div>');
    text = text.replace(/\n+<div class="divider"><\/div>\n+/g, "\n<div class=\"divider\"></div>\n")

    // 转换列表
    text = text.replace(/\n( *[\*-] ([^\n]+)\n){1,}/gs, (match, link, text) => {
        match = match.replace(/^[\*-] (.+)/gm, '<li class="i0">$1</li>');
        match = match.replace(/^ [\*-] (.+)/gm, '<li class="i1">$1</li>');
        match = match.replace(/^  [\*-] (.+)/gm, '<li class="i2">$1</li>');
        match = match.replace(/^   [\*-] (.+)/gm, '<li class="i3">$1</li>');
        return `\n<ul>${match}</ul>`;
    });

    text = text.replace(/\n([0-9]{1,}\. ([^\n]+)\n){2,}/gs, (match, link, text) => {

        match = match.replace(/^[0-9]{1,}\. (.+)/gm, '<li class="i0">$1</li>');
        console.log(match)
        return `\n<ol>${match}</ol>`;
    });

    // text = text.replace(/^[\*-] (.+)/gm, '<li class="i0">$1</li>');
    // text = text.replace(/^ [\*-] (.+)/gm, '<li class="i1">$1</li>');
    // text = text.replace(/^  [\*-] (.+)/gm, '<li class="i2">$1</li>');
    // text = text.replace(/^   [\*-] (.+)/gm, '<li class="i3">$1</li>');
    // text = text.replace(/(<li class="i[0-9]">.*<\/li>)/gs, '<ul>$1</ul>');

    // text = text.replace(/^[0-9]+\. (.+)/gm, '<li>$1</li>').replace(/(<li>.*<\/li>)/gs, '<ol>$1</ol>');

    // 转换表格
    text = text.replace(/{\|([\s\S]*?)\|}/g, (match, content) => {
        return `<table>${content.replace(/^\|-(.+)/gm, '<tr><td>$1</td></tr>')}</table>`;
    });

    text = text.replace(/\n((\|[^\|]*\|){1,}\n){1,}/g, (match) => {
        console.log(match)
        return match;
    });

    // 转换链接和粗体
    text = text.replace(/\[\[([^\|]+?)\|?(.+?)?\]\]/g, (match, link, text) => {
        return `<a href="${link}">${text || link}</a>`;
    });
    text = text.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>');
    text = text.replace(/'''(.+?)'''/g, '<strong>$1</strong>');
    text = text.replace(/\n{2,}/g, "\n</br>")

    text = text.replace(/`(.+?)`/g, '<span class="quote">$1</span>');

    for (let i = quotes.length; i--;) {
        text = text.replace(new RegExp('<quote>' + i + '<\\/quote>', 'g'), `<span class="quote">${quotes[i]}</span>`)
    }

    for (let i = codes.length; i--;) {
        const coding = codes[i]
        text = text.replace(new RegExp('<coding>' + i + '<\\/coding>', 'g'), `<pre ref="codeBlock" class="code ${coding['lang']}">${coding['code']}</pre>\n`)
    }

    return `<div class="markup">${text}</div>`;
}

function addMessage(content, isUser = false) {
    const messageDiv = document.createElement('div');
    messageDiv.className = `message ${isUser ? 'user-message' : 'bot-message'}`;

    // 仅对机器人消息转换 Wiki 格式
    if (!isUser) {
        messageDiv.innerHTML = wikiToHtml(content);
        // 高亮代码块
        messageDiv.querySelectorAll('pre.code').forEach(block => {
            hljs.highlightElement(block);
        });
    } else {
        messageDiv.textContent = content;
    }

    chatMessages.appendChild(messageDiv);
    chatMessages.scrollTop = chatMessages.scrollHeight;
}

// 显示加载状态
function showLoading() {
    const loadingDiv = document.createElement('div');
    loadingDiv.className = 'message loading bot-message';

    loadingDiv.innerHTML = `<div class="temp"></div><div class="dot-flashing"></div>`;

    chatMessages.appendChild(loadingDiv);
    chatMessages.scrollTop = chatMessages.scrollHeight;
    return loadingDiv;
}

function trimHistory(history, maxRounds = 5) {
    if (history.length > maxRounds * 2) {
        return history.slice(-maxRounds * 2);
    }
    return history;
}

function extractFirstAndRemoveFirstThinkTag(str) {
    // 匹配并替换第一个<think>标签
    str = str || ""
    let extracted = [];
    const cleanedStr = str.replace(/<think[^<>]*>([\s\S]*?)<\/think>/, (match, p1) => {
        extracted.push(p1);
        return ''; // 替换第一个匹配项为空
    });
    return { extracted, cleanedStr };
}

const model = localStorage.getItem('model');
const apiUrl = localStorage.getItem('url');
const apiKey = localStorage.getItem('key');
if (!(apiKey && apiUrl && model)) {
    location.href = 'options.html'
}

function initSessionList(el, select) {
    var methods = {}
    const navs = document.getElementById('session-list-nav');
    function showSessions() {
        let sessions = JSON.parse(localStorage.getItem('sessions') || '[]')
        el.style.display = 'block'
        navs.innerHTML = ""

        for (let i = sessions.length; i--;) {
            const s = sessions[i]
            if (s['session_id'] && s['create_time'] & s['update_time']) {
                const ne = document.createElement("div");
                const m = s['session_id'].split('_')[0];
                ne.innerHTML = [
                    '<div>',
                    `<div class="li-model-tip"><span class="li-model-span">${m}</span>&nbsp;/&nbsp;${new Date(s['update_time'])}</div>`,
                    `<div><span class="li-content">${s['item']['content']}</span></div>`,
                    '</div>'
                ]
                    .join("\n"); // 设置内容
                // 可选：添加样式或属性
                ne.className = "session-li";
                navs.appendChild(ne)
                ne.addEventListener('click', async () => {
                    select(sessions[i], methods)
                });
            }
        }
    }

    function hideSessions() {
        el.style.display = 'none'
    }

    document.getElementById('session-list-mask').addEventListener('click', async () => {
        hideSessions(el)
    });

    document.getElementById('new-session-a').addEventListener('click', async () => {
        select(null, methods)
    });

    methods = {
        showSessions: showSessions,
        hideSessions: hideSessions
    }

    // showSessions()
    return methods
}

// const models = ['qwen-max-latest', 'qwen-max', 'qwen-plus']
let vm = new Vue({
    el: "#main-div",
    data: {
        session_time: new Date().getTime(),
        sid: '',
        models: model.split(','),
        model: model.split(',')[0],
        chatHistory: [],
        messages: [],
        loading: false,
        sendText: "",
        sendLines: 0,
        partial: "",
        sop: {}
    },
    created: function () {

    },
    watch: {
        sendText: function () {
            const input = document.getElementById('message-input')
            const nl = this.sendText.split("\n").length
            if (nl < this.sendLines) {
                input.style.height = '48px'
                input.style.height = input.scrollHeight
            } else {
                input.style.height = input.scrollHeight
            }
            this.sendLines = nl
        }

    },
    mounted: function () {
        const self = this;
        const sendButton = document.getElementById('send-button');
        const messageInput = document.getElementById('message-input');
        const historyBtn = document.getElementById('history-button');
        setTimeout(() => {
            document.getElementById('main-body').style.padding = '0px';
        }, 100);
        sendButton.addEventListener('click', async () => {
            if (self.sendText) {
                if (self.sendText == 'clear') {
                    self.clearSession(self.sid)
                    self.startSession()
                    self.sendText = ''
                    return
                }
                self.addHistory({ role: 'user', content: self.sendText })
                self.addMessage(self.sendText, true);
                self.sendText = ""
                self.sendToOllama();
            } else if (self.chatHistory.length > 1) {
                let last = self.chatHistory.pop()
                while (last.role !== 'user') {
                    last = self.chatHistory.pop()
                }

                self.chatHistory.push(last)
                self.addMessage(last.content, true);
                self.sendToOllama();
            }

        });

        historyBtn.addEventListener('click', () => {
            if (this.sop) {
                this.sop.showSessions()
            }
        })

        messageInput.addEventListener('keypress', (e) => {
            if (e.key === 'Enter' && !e.shiftKey) {
                e.preventDefault();
                sendButton.click();
            }
        });
        if (location.hash.indexOf('_') > 1) {
            // const m = location.hash.substr(1).split('_')[0]
            // this.sid = `${m}_${this.session_time}`
            // location.hash = `#${this.sid}`
            this.startSession(location.hash.substr(1))
        } else {
            this.sid = `${this.model}_${new Date().getTime()}`
            this.startSession()
        }

        this.sop = initSessionList(document.getElementById('session-list'), (session, op) => {
            if (session) {
                this.startSession(session['session_id'])
            } else {
                this.startNewSession()
            }

            op.hideSessions()
        })

        // this.scrollTop = document.getElementById('chat-messages')?.scrollTop || 0
    },
    computed: {
        previewText() {
            return this.partial.trim().replace(/^<think>\s*<\/think>/g, "").trim()
        }
    },
    updated() {
        let self = this
        this.$nextTick(() => {
            document.getElementById('chat-messages').querySelectorAll('pre.code').forEach(block => {
                hljs.highlightElement(block);
                block.className = ""
            });
            if (this.partial) {
                document.getElementById('chat-messages').scrollTop = document.getElementById('chat-messages').scrollHeight;
            }
        });
    },
    methods: {
        cp2clipboard(content) {
            // 检查权限
            if (navigator.clipboard) {
                // navigator.clipboard.writeText(this.md2wiki(content.trim())).then(() => {
                navigator.clipboard.writeText(content.trim()).then(() => {
                    console.log("内容已成功复制到剪切板");
                }).catch(err => {
                    console.error("复制失败:", err);
                });
            } else {
                alert("您的浏览器不支持该操作，请使用现代浏览器如Chrome、Firefox等。");
            }
        },
        md2wiki(text) {
            let codes = []
            let quotes = []
            text = text.trim()
            text = text.replace(/``` *(\w+)? *\n([\s\S]*?)```/g, (match, lang, code) => {
                let idx = codes.length;
                codes.push({
                    "lang": lang || '',
                    "code": code.trim()
                })
                return lang ? `{{{#!${lang}\n${code.trim()}\n}}}` : `{{{\n${code.trim()}\n}}}`
            });

            // 转换标题
            text = text.replace(/^====(.+?)====/gm, '==== $1');
            text = text.replace(/^===(.+?)===/gm, '=== $1');
            text = text.replace(/^==(.+?)==/gm, '== $1');
            text = text.replace(/^=(.+?)=/gm, '= $1');
            text = text.replace(/^##### +([\s\S]*?)$/gm, '===== $1');
            text = text.replace(/^#### +([\s\S]*?)$/gm, '==== $1');
            text = text.replace(/^### +([\s\S]*?)$/gm, '=== $1');
            text = text.replace(/^## +([\s\S]*?)$/gm, '== $1');
            text = text.replace(/^# +([\s\S]*?)$/gm, '= $1');
            text = text.replace(/^-{3,} *$/gm, '------');

            // 转换链接和粗体
            text = text.replace(/\[\[([^\|]+?)\|?(.+?)?\]\]/g, (match, link, text) => {
                return `[${link} ${text} ${link}]`
            });
            // text = text.replace(/'''(.+?)'''/g, '<strong>$1</strong>');
            text = text.replace(/\*\*(.+?)\*\*/g, "'''$1'''");

            return text;
        },
        selectModel(model) {
            this.model = model
            this.sid = `${this.model}_${this.sid.split('_')[1]}`
            location.hash = `#${this.sid}`
            this.startSession()
        },
        clearSession(sid) {
            if (sid) {
                localStorage.removeItem(sid)
                let sessions = JSON.parse(localStorage.getItem('sessions') || '[]');
                sessions = sessions.filter(item => item['session_id'] != sid)
                console.log(sessions.length);
                localStorage.setItem('sessions', JSON.stringify(sessions))
            }
            // else{
            //     localStorage.setItem('sessions', '[]');
            // }
        },
        startNewSession() {
            this.sid = `${this.model}_${new Date().getTime()}`
            location.hash = `#${this.sid}`
            this.startSession()
        },
        startSession(session_id) {
            if (session_id) {
                let m = session_id.split('_')[0]
                this.sid = session_id
                this.selectModel(m)
            }
            location.hash = `#${this.sid}`
            this.chatHistory = []
            this.messages = []

            const str = localStorage.getItem(this.sid)
            if (str) {
                let items = JSON.parse(str);
                if (items.length > 1) {
                    this.chatHistory = items
                    for (let i = 0; i < items.length; i++) {
                        this.addMessage(items[i]['content'], items[i]['role'] == 'user')
                    }
                } else if (items.length == 1 && items[0].role == 'user') {
                    // console.log(items[0].content)
                    this.sendText = items[0].content;
                }
            }
        },
        addHistory(item) {
            if (this.chatHistory.length == 0) {
                let sessions = JSON.parse(localStorage.getItem('sessions') || '[]')
                sessions.push({
                    'session_id': this.sid,
                    'item': item,
                    'history_count': 1,
                    'create_time': new Date().getTime(),
                    'update_time': new Date().getTime()
                })
                localStorage.setItem('sessions', JSON.stringify(sessions));
            }
            this.chatHistory.push(item);
            localStorage.setItem(this.sid, JSON.stringify(this.chatHistory));
        },
        addMessage(msg, isUser) {
            // console.log(msg)
            for (let i = this.messages.length; i--;) {
                this.messages[i]['tfolded'] = true
            }
            if (isUser) {
                this.messages.push({
                    raw: msg,
                    content: msg,
                    thinking: "",
                    isUser: !!isUser,
                    tfolded: false,
                    cfolded: true,
                    rawPresent: false
                })
            } else {
                let r = extractFirstAndRemoveFirstThinkTag(msg)

                this.messages.push({
                    raw: r.cleanedStr,
                    content: wikiToHtml(r.cleanedStr).trim(),
                    thinking: r.extracted.length > 0 ? r.extracted[0].trim() : "",
                    isUser: !!isUser,
                    tfolded: false,
                    cfolded: false,
                    rawPresent: false
                })
            }
        },
        sendToOllama(next) {
            let self = this;
            self.chatHistory = trimHistory(self.chatHistory, 8);
            self.loading = true
            next = next || function () { }

            const sid = `${(new Date()).getTime()}`

            function messageListener(request, sender, sendResponse) {
                if (request.action === `stream_${sid}`) {
                    if (request.chunk) {
                        self.partial += request.chunk
                    }
                }
            }
            chrome.runtime.onMessage.addListener(messageListener)
            chrome.runtime.sendMessage({
                action: "queryAI",
                stream: sid,
                query: JSON.stringify({
                    model: self.model,
                    messages: self.chatHistory
                })
            }, function (response) {
                chrome.runtime.onMessage.removeListener(messageListener)

                self.loading = false

                if (self.partial === self.content) {
                    self.addHistory({ role: 'assistant', content: self.partial });
                }
                self.addMessage(response.content, false)
                self.partial = ''

            });

        }
    }
})

// 监听 DOM 变化，确保动态加载的内容也能被处理
// const observer = new MutationObserver(() => {
//     console.log('hello world')
// });

// observer.observe(document.getElementById('message-input'), { childList: true, subtree: true });